Operation

In order to work with RCy3 you must have Cytoscape v3.7 or later installed and running. Cytoscape can be installed from cytoscape.org. The RCy3 package can be installed from Bioconductor:

Launch Cytoscape and keep it running whenever using RCy3. Confirm that you have everything installed and that RCy3 is communicating with Cytoscape via CyREST:

As with any R package, one can access the documentation and browse over a dozen vignettes included in the RCy3 package:

Use Cases

The following sections demonstrate a variety of common and advanced network biology use cases as runnable R code snippets. The first set focuses on fundamental Cytoscape operations that are common to most use cases:

  • Loading networks (from R objects, Cytoscape files and public databases)
  • Visualizing network data
  • Filtering by node degree or data
  • Saving and exporting networks

Additionally, there are examples that demonstrate analytical workflows, relying not only on Cytoscape, but also on Cytoscape apps and other R packages:

  • Building maps of enrichment analysis results using EnrichmentMap and AutoAnnotate
  • Visualizing integrated network analysis using BioNet
  • Performing advanced graph analytics using RBGL

##Loading Networks Networks come in all shapes and sizes in multiple formats from multiple sources. Here are just a few of the myriad ways to load networks into Cytoscape using RCy3.

From R Objects. . .

From Cytoscape-supported File Formats. . .

From Public Databases via Cytoscape Apps. . .

Building Maps of Enrichment Analysis Results

This workflow illustrates how to plot an annotated map of enrichment results using the EnrichmentMap Pipeline Collection of apps in Cytoscape. An enrichment map is a network visualization of related genesets in which nodes are gene sets (or pathways) and edge weight indicates the overlap in member genes. Following the construction of the enrichment map, AutoAnnotate clusters redundant gene sets and uses WordCloud to label the resulting cluster. The code uses the Commands interface to invoke EnrichmentMap and AutoAnnotate apps. After installing apps, run commandsAPI() to open the live Swagger documentation to browse and execute command-line syntax.

Visualizing Integrated Network Analysis Using BioNet

The BioNet package implements analytical methods to perform integrated network analysis, e.g., of gene expression data and clinical survival data in the context of protein-protein interaction networks. Partnered with RCy3, the analytical results from BioNet can be visualized in Cytoscape with vastly more options for customization. Starting with the “Quick Start” tutorial from BioNet, we pass the results directly to Cytoscape for visualization:

##Performing Advanced Graph Analytics Using RBGL As an interface to the BOOST library, the RBGL Bioconductor package offers an impressive array of analytical functions for graphs. Here we will start with a network in Cytoscape, load it into R as a graph object, perform shortest path calculation using RBGL and then visualize the results back in Cytoscape.

LS0tCnRpdGxlOiAiUkN5MyBVc2UgQ2FzZXMiCmF1dGhvcjogIkFsZXggUGljbywgSnVsaWEgR3VzdGF2c2VuLCBTaHJhZGRoYSBQYWksIFJ1dGggSXNzZXJsaW4sIEJhcnJ5IERlbWNoYWsiCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogIm5vbmUiCiMgIHBkZl9kb2N1bWVudDoKIyAgICB0b2M6IHRydWUgIAotLS0KYGBge3IsIGVjaG8gPSBGQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGV2YWw9RkFMU0UKKQpgYGAKCiMgT3BlcmF0aW9uCkluIG9yZGVyIHRvIHdvcmsgd2l0aCBSQ3kzIHlvdSBtdXN0IGhhdmUgQ3l0b3NjYXBlIHYzLjcgb3IgbGF0ZXIgaW5zdGFsbGVkIGFuZCBydW5uaW5nLiAgQ3l0b3NjYXBlIGNhbiBiZSBpbnN0YWxsZWQgZnJvbSBbY3l0b3NjYXBlLm9yZ10oaHR0cHM6Ly9jeXRvc2NhcGUub3JnKS4gVGhlIFJDeTMgcGFja2FnZSBjYW4gYmUgaW5zdGFsbGVkIGZyb20gW0Jpb2NvbmR1Y3Rvcl0oaHR0cHM6Ly9iaW9jb25kdWN0b3Iub3JnL3BhY2thZ2VzL3JlbGVhc2UvYmlvYy9odG1sL1JDeTMuaHRtbH17QmlvY29uZHVjdG9yKToKYGBge3IsIGV2YWw9RkFMU0V9CmlmICghcmVxdWlyZU5hbWVzcGFjZSgiQmlvY01hbmFnZXIiLCBxdWlldGx5ID0gVFJVRSkpCiAgaW5zdGFsbC5wYWNrYWdlcygiQmlvY01hbmFnZXIiKQpCaW9jTWFuYWdlcjo6aW5zdGFsbCgiUkN5MyIpCmxpYnJhcnkoUkN5MykKYGBgCgpMYXVuY2ggQ3l0b3NjYXBlIGFuZCBrZWVwIGl0IHJ1bm5pbmcgd2hlbmV2ZXIgdXNpbmcgUkN5My4gQ29uZmlybSB0aGF0IHlvdSBoYXZlIGV2ZXJ5dGhpbmcgaW5zdGFsbGVkIGFuZCB0aGF0IFJDeTMgaXMgY29tbXVuaWNhdGluZyB3aXRoIEN5dG9zY2FwZSB2aWEgQ3lSRVNUOgpgYGB7cn0KY3l0b3NjYXBlUGluZyAoKQojWzFdICJZb3UgYXJlIGNvbm5lY3RlZCB0byBDeXRvc2NhcGUhIgpgYGAKCkFzIHdpdGggYW55IFIgcGFja2FnZSwgb25lIGNhbiBhY2Nlc3MgdGhlIGRvY3VtZW50YXRpb24gYW5kIGJyb3dzZSBvdmVyIGEgZG96ZW4gdmlnbmV0dGVzIGluY2x1ZGVkIGluIHRoZSBSQ3kzIHBhY2thZ2U6CmBgYHtyfQpoZWxwKHBhY2thZ2U9UkN5MykKYnJvd3NlVmlnbmV0dGVzKCJSQ3kzIikKYGBgCgojIFVzZSBDYXNlcwpUaGUgZm9sbG93aW5nIHNlY3Rpb25zIGRlbW9uc3RyYXRlIGEgdmFyaWV0eSBvZiBjb21tb24gYW5kIGFkdmFuY2VkIG5ldHdvcmsgYmlvbG9neSB1c2UgY2FzZXMgYXMgcnVubmFibGUgUiBjb2RlIHNuaXBwZXRzLiBUaGUgZmlyc3Qgc2V0IGZvY3VzZXMgb24gZnVuZGFtZW50YWwgQ3l0b3NjYXBlIG9wZXJhdGlvbnMgdGhhdCBhcmUgY29tbW9uIHRvIG1vc3QgdXNlIGNhc2VzOgoKKiBMb2FkaW5nIG5ldHdvcmtzIChmcm9tIFIgb2JqZWN0cywgQ3l0b3NjYXBlIGZpbGVzIGFuZCBwdWJsaWMgZGF0YWJhc2VzKQoqIFZpc3VhbGl6aW5nIG5ldHdvcmsgZGF0YQoqIEZpbHRlcmluZyBieSBub2RlIGRlZ3JlZSBvciBkYXRhCiogU2F2aW5nIGFuZCBleHBvcnRpbmcgbmV0d29ya3MKCkFkZGl0aW9uYWxseSwgdGhlcmUgYXJlIGV4YW1wbGVzIHRoYXQgZGVtb25zdHJhdGUgYW5hbHl0aWNhbCB3b3JrZmxvd3MsIHJlbHlpbmcgbm90IG9ubHkgb24gQ3l0b3NjYXBlLCBidXQgYWxzbyBvbiBDeXRvc2NhcGUgYXBwcyBhbmQgb3RoZXIgUiBwYWNrYWdlczoKCiogQnVpbGRpbmcgbWFwcyBvZiBlbnJpY2htZW50IGFuYWx5c2lzIHJlc3VsdHMgdXNpbmcgRW5yaWNobWVudE1hcCBhbmQgQXV0b0Fubm90YXRlCiogVmlzdWFsaXppbmcgaW50ZWdyYXRlZCBuZXR3b3JrIGFuYWx5c2lzIHVzaW5nIEJpb05ldAoqIFBlcmZvcm1pbmcgYWR2YW5jZWQgZ3JhcGggYW5hbHl0aWNzIHVzaW5nIFJCR0wKCiMjTG9hZGluZyBOZXR3b3JrcwpOZXR3b3JrcyBjb21lIGluIGFsbCBzaGFwZXMgYW5kIHNpemVzIGluIG11bHRpcGxlIGZvcm1hdHMgZnJvbSBtdWx0aXBsZSBzb3VyY2VzLiBIZXJlIGFyZSBqdXN0IGEgZmV3IG9mIHRoZSBteXJpYWQgd2F5cyB0byBsb2FkIG5ldHdvcmtzIGludG8gQ3l0b3NjYXBlIHVzaW5nIFJDeTMuCgpGcm9tIFIgT2JqZWN0cy4gLiAuCmBgYHtyfQojIEZyb20gZ3JhcGggb2JqZWN0cyAoZ3JhcGhORUwpICAKZyA8LSBtYWtlU2ltcGxlR3JhcGgoKQpjcmVhdGVOZXR3b3JrRnJvbUdyYXBoKGcpCiMjIEFuZCByb3VuZC10cmlwIGJhY2sgZnJvbSBDeXRvc2NhcGUgdG8gZ3JhcGggCmcyIDwtIGNyZWF0ZUdyYXBoRnJvbU5ldHdvcmsoKQoKIyBGcm9tIGlncmFwaCBvYmplY3RzCmxpYnJhcnkoaWdyYXBoKQppZyA8LSBtYWtlX2dyYXBoKCJaYWNoYXJ5IikKY3JlYXRlTmV0d29ya0Zyb21JZ3JhcGgoaWcpCiMjIEFuZCByb3VuZC10cmlwIGJhY2sgZnJvbSBDeXRvc2NhcGUgdG8gaWdyYXBoCmlnMiA8LSBjcmVhdGVJZ3JhcGhGcm9tTmV0d29yaygpCiMjIE5vdGUgdGhhdCB0aGUgQ3l0b3NjYXBlIG1vZGVsIGluZmVycyBkaXJlY3Rpb25hbGl0eQoKIyBGcm9tIGRhdGFmcmFtZXMKbm9kZXMgPC0gZGF0YS5mcmFtZShpZD1jKCJub2RlIDAiLCJub2RlIDEiLCJub2RlIDIiLCJub2RlIDMiKSwKICAgICAgICAgICAgICAgICAgICBncm91cD1jKCJBIiwiQSIsIkIiLCJCIiksICNjYXRlZ29yaWNhbCBzdHJpbmdzCiAgICAgICAgICAgICAgICAgICAgc2NvcmU9YXMuaW50ZWdlcihjKDIwLDEwLDE1LDUpKSwgI2ludGVnZXJzCiAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkKZWRnZXMgPC0gZGF0YS5mcmFtZShzb3VyY2U9Yygibm9kZSAwIiwibm9kZSAwIiwibm9kZSAwIiwibm9kZSAyIiksCiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0PWMoIm5vZGUgMSIsIm5vZGUgMiIsIm5vZGUgMyIsIm5vZGUgMyIpLAogICAgICAgICAgICAgICAgICAgIGludGVyYWN0aW9uPWMoImluaGliaXRzIiwiaW50ZXJhY3RzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiYWN0aXZhdGVzIiwiaW50ZXJhY3RzIiksICAjb3B0aW9uYWwKICAgICAgICAgICAgICAgICAgICB3ZWlnaHQ9Yyg1LjEsMy4wLDUuMiw5LjkpLCAjbnVtZXJpY3MKICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQpjcmVhdGVOZXR3b3JrRnJvbURhdGFGcmFtZXMobm9kZXMsIGVkZ2VzKQpgYGAKCkZyb20gQ3l0b3NjYXBlLXN1cHBvcnRlZCBGaWxlIEZvcm1hdHMuIC4gLgpgYGB7cn0KIyBGcm9tIEN5dG9zY2FwZSBzZXNzaW9uIGZpbGVzCiMjIFdpbGwgZXJhc2UgYW5kIHJlcGxhY2UgYWxsIGRhdGEgZnJvbSBjdXJyZW50IHNlc3Npb24hCm9wZW5TZXNzaW9uKCkgIyBkZWZhdWx0IGZpbGUgPSBnYWxGaWx0ZXJlZC5jeXMKCiMgRnJvbSBsb2NhbCBuZXR3b3JrIGZpbGVzCmltcG9ydE5ldHdvcmtGcm9tRmlsZSgpICMgZGVmYXVsdCBmaWxlID0gZ2FsRmlsdGVyZWQuc2lmCiMjIFN1cHBvcnRlZCBmaWxlIGZvcm1hdHM6IFNJRiwgR01MLCB4R01NTCwgZ3JhcGhNTCwgQ1gsIHBsdXMKCiMgRnJvbSBOREV4LCB0aGUgbmV0d29yayBkYXRhYmFzZQppbXBvcnROZXR3b3JrRnJvbU5ERXgoIjViZTg1ODE3LTFlNWYtMTFlOC1iOTM5LTBhYzEzNWU4YmFjZiIpCiMjIEFjY291bnQgaW5mb3JtYXRpb24gb3IgYWNjZXNzS2V5IGFyZSByZXF1aXJlZCBhcmd1bWVudHMgb25seQojIyB3aGVuIGFjY2Vzc2luZyBwcml2YXRlIGNvbnRlbnQKYGBgCgpGcm9tIFB1YmxpYyBEYXRhYmFzZXMgdmlhIEN5dG9zY2FwZSBBcHBzLiAuIC4KYGBge3J9CiMgRnJvbSBTVFJJTkcsIHN0YXJ0aW5nIHdpdGggYSBsaXN0IG9mIGdlbmVzL3Byb3RlaW5zCmluc3RhbGxBcHAoInN0cmluZ0FwcCIpCmdlbmUubGlzdCA8LSBjKCJUNTMiLCJBS1QxIiwiQ0RLTjFBIikKZ2VuZS5zdHIgPC0gcGFzdGUoZ2VuZS5saXN0LCBjb2xsYXBzZSA9ICIsIikKc3RyaW5nLmNtZCA8LSBwYXN0ZSgic3RyaW5nIHByb3RlaW4gcXVlcnkgY3V0b2ZmPTAuOTkgbGltaXQ9NDAgcXVlcnkiLAogICAgICAgICAgICAgICAgICAgIGdlbmUuc3RyLCBzZXAgPSAiPSIpCmNvbW1hbmRzUnVuKHN0cmluZy5jbWQpCgojIEZyb20gV2lraVBhdGh3YXlzLCBzdGFydGluZyB3aXRoIGEga2V5d29yZApsaWJyYXJ5KHJXaWtpUGF0aHdheXMpICMgaW5zdGFsbCBmcm9tIEJpb2NvbmR1Y3RvcgppbnN0YWxsQXBwKCJXaWtpUGF0aHdheXMiKQprZXl3b3JkIDwtICJnbGlvYmxhc3RvbWEiCmdibS5wYXRod2F5cyA8LSBmaW5kUGF0aHdheXNCeVRleHQoa2V5d29yZCkKZ2JtLndwaWQgPC0gZ2JtLnBhdGh3YXlzW1sxXV0kaWQgIyBsZXTigJlzIGp1c3QgdGFrZSB0aGUgZmlyc3Qgb25lCndpa2lwYXRod2F5cy5jbWQgPC0gcGFzdGUoIndpa2lwYXRod2F5cyBpbXBvcnQtYXMtcGF0aHdheSBpZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ2JtLndwaWQsIHNlcCA9ICI9IikKY29tbWFuZHNSdW4od2lraXBhdGh3YXlzLmNtZCkKYGBgCgojIyBWaXN1YWxpemluZyBEYXRhIG9uIE5ldHdvcmtzCkN5dG9zY2FwZSBleGNlbHMgYXQgZ2VuZXJhdGluZyBwdWJsaWNhdGlvbi1xdWFsaXR5IG5ldHdvcmsgdmlzdWFsaXphdGlvbiB3aXRoIGRhdGEgb3ZlcmxheXMuIFRoaXMgdmlnbmV0dGUgZGVtb25zdHJhdGVzIGp1c3Qgb25lIG9mIHRoZSBodW5kcmVkcyBvZiB2aXN1YWwgc3R5bGUgbWFwcGluZyBvcHRpb25zIHVzaW5nIFJDeTMuCmBgYHtyfQojIExvYWQgc2FtcGxlIG5ldHdvcmsKY2xvc2VTZXNzaW9uKEZBTFNFKSAjIGNsZWFycyBhbGwgc2Vzc2lvbiBkYXRhIHdpaHRvdXQgc2F2aW5nCmltcG9ydE5ldHdvcmtGcm9tRmlsZSgpICMgZGVmYXVsdCBmaWxlID0gZ2FsRmlsdGVyZWQuc2lmCgojIExvYWQgc2FtcGxlIGRhdGEKY3N2IDwtIHN5c3RlbS5maWxlKCJleHRkYXRhIiwiZ2FsRXhwRGF0YS5jc3YiLCBwYWNrYWdlPSJSQ3kzIikKZGF0YSA8LSByZWFkLmNzdihjc3YsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKbG9hZFRhYmxlRGF0YShkYXRhLGRhdGEua2V5LmNvbHVtbj0ibmFtZSIpCgojIFByZXBhcmUgZGF0YS1tYXBwaW5nIHBvaW50cwpnYWw4MFJleHAubWluIDwtIG1pbihkYXRhJGdhbDgwUmV4cCwgbmEucm0gPSBUUlVFKQpnYWw4MFJleHAubWF4IDwtIG1heChkYXRhJGdhbDgwUmV4cCwgbmEucm0gPSBUUlVFKQojIyBGb3IgYSBiYWxhbmNlZCBjb2xvciBncmFkaWVudCwgcGljayB0aGUgbGFyZ2VzdCBhYnNvbHV0ZSB2YWx1ZQpnYWw4MFJleHAubWF4LmFicyA8LSBtYXgoYWJzKGdhbDgwUmV4cC5taW4pLCBhYnMoZ2FsODBSZXhwLm1heCkpIAoKIyBTZXQgbm9kZSBjb2xvciBncmFkaWVudCBmcm9tIGJsdWUgdG8gd2hpdGUgdG8gcmVkCnNldE5vZGVDb2xvck1hcHBpbmcoJ2dhbDgwUmV4cCcsIGMoLWdhbDgwUmV4cC5tYXguYWJzLCAwLCBnYWw4MFJleHAubWF4LmFicyksIAogICAgICAgICAgICAgICAgICAgIGMoJyM1NTc3RkYnLCcjRkZGRkZGJywnI0ZGNzc1NScpLCBkZWZhdWx0LmNvbG9yID0gJyM5OTk5OTknKQoKYGBgCgojIyBGaWx0ZXJpbmcgTmV0d29ya3MgYnkgRGVncmVlIGFuZCBieSBEYXRhCk5ldHdvcmsgdG9wb2xvZ3kgYW5kIGFzc29jaWF0ZWQgbm9kZSBvciBlZGdlIGRhdGEgY2FuIGJlIHVzZWQgdG8gbWFrZSBzZWxlY3Rpb25zIGluIEN5dG9zY2FwZSB0aGF0IGVuYWJsZSBmaWx0ZXJpbmcgYW5kIHN1Ym5ldHdvcmtpbmcuIFRoZSBmaWx0ZXJzIGFyZSBhZGRlZCB0byB0aGUgU2VsZWN0IHRhYiBpbiB0aGUgQ29udHJvbCBQYW5lbCBvZiBDeXRvc2NhcGXigJlzIEdVSSBhbmQgc2F2ZWQgaW4gc2Vzc2lvbiBmaWxlcy4KYGBge3J9CiMgTG9hZCBkZW1vIEN5dG9zY2FwZSBzZXNzaW9uIGZpbGUKb3BlblNlc3Npb24oKSAjIGRlZmF1bHQgZmlsZSA9IGdhbEZpbHRlcmVkLmN5cwpuZXQuc3VpZCA8LSBnZXROZXR3b3JrU3VpZCgpICMgZ2V0IFNVSUQgZm9yIGZ1dHVyZSByZWZlcmVuY2UKCiMgRmlsdGVyIGZvciBuZWlnaGJvcnMgb2YgaGlnaCBkZWdyZWUgbm9kZXMKY3JlYXRlRGVncmVlRmlsdGVyKGZpbHRlci5uYW1lID0gImRlZ3JlZSBmaWx0ZXIiLAogICAgICAgICAgICAgICAgICAgY3JpdGVyaW9uID0gYygwLDkpLAogICAgICAgICAgICAgICAgICAgcHJlZGljYXRlID0gIklTX05PVF9CRVRXRUVOIikKc2VsZWN0Rmlyc3ROZWlnaGJvcnMoKSAjIGV4cGFuZCBzZWxlY3Rpb24gdG8gZmlyc3QgbmVpZ2hib3JzCmNyZWF0ZVN1Ym5ldHdvcmsoc3VibmV0d29yay5uYW1lID0gImZpcnN0IG5laWdoYm9ycyBvZiBoaWdoIGRlZ3JlZSBub2RlcyIpCgojIEZpbHRlciBmb3IgaGlnaCBlZGdlIGJldHdlZW5uZXNzCmNyZWF0ZUNvbHVtbkZpbHRlcihmaWx0ZXIubmFtZSA9ICJlZGdlIGJldHdlZW5uZXNzIiwKICAgICAgICAgICAgICAgICAgIHR5cGUgPSAiZWRnZXMiLAogICAgICAgICAgICAgICAgICAgY29sdW1uID0gIkVkZ2VCZXR3ZWVubmVzcyIsCiAgICAgICAgICAgICAgICAgICA0MDAwLAogICAgICAgICAgICAgICAgICAgIkdSRUFURVJfVEhBTiIsCiAgICAgICAgICAgICAgICAgICBuZXR3b3JrID0gbmV0LnN1aWQpCmNyZWF0ZVN1Ym5ldHdvcmsoc3VibmV0d29yay5uYW1lID0gImhpZ2ggZWRnZSBiZXR3ZWVubmVzcyIpCmBgYAoKIyMgU2F2aW5nIGFuZCBFeHBvcnRpbmcgTmV0d29ya3MKVGhlcmUgYXJlIGxvY2FsIGFuZCBjbG91ZC1ob3N0ZWQgb3B0aW9ucyBmb3Igc2F2aW5nIGFuZCBzaGFyaW5nIG5ldHdvcmsgbW9kZWxzIGFuZCBpbWFnZXMuIFRoZSBDeXRvc2NhcGUgc2Vzc2lvbiBmaWxlIChDWVMpIHdpbGwgaW5jbHVkZSBhbGwgbmV0d29ya3MsIGNvbGxlY3Rpb25zLCB0YWJsZXMgYW5kIHN0eWxlcy4gSXQgc2hvdWxkIHJldGFpbiBldmVyeSBhc3BlY3Qgb2YgeW91ciBzZXNzaW9uLCBpbmNsdWRpbmcgdGhlIHNpemUgb2YgdGhlIGFwcGxpY2F0aW9uIHdpbmRvdy4gTmV0d29yayBhbmQgaW1hZ2UgZXhwb3J0cyBpbmNsdWRlIG9ubHkgdGhlIGN1cnJlbnRseSBhY3RpdmUgbmV0d29yay4gRXhwb3J0IHRvIE5ERXggcmVxdWlyZXMgYWNjb3VudCBpbmZvcm1hdGlvbiB5b3UgY2FuIG9idGFpbiBmcm9tIFtuZGV4YmlvLm9yZ10oaHR0cHM6Ly9uZGV4YmlvLm9yZykuCmBgYHtyfQojIFNhdmluZyBzZXNzaW9ucwpzYXZlU2Vzc2lvbigiTXlTZXNzaW9uIikgIy5jeXMKIyMgTGVhdmUgZmlsZW5hbWUgYmxhbmsgdG8gdXBkYXRlIHByZXZpb3VzbHkgc2F2ZWQgc2Vzc2lvbiBmaWxlCgojIEV4cG9ydGluZyBpbWFnZXMgYW5kIG5ldHdvcmtzCmV4cG9ydE5ldHdvcmsoKSAjLnNpZgojIyBPcHRpb25hbGx5IHNwZWNpZnkgZmlsZW5hbWUsIGRlZmF1bHQgaXMgbmV0d29yayBuYW1lCiMjIE9wdGlvbmFsbHkgc3BlY2lmeSB0eXBlOiBTSUYoZGVmYXVsdCksIENYLCBjeWpzLCBncmFwaE1MLCBOTkYsIFNJRiwgeEdNTUwKZXhwb3J0SW1hZ2UodHlwZT0ncG5nJykgIy5wbmcKIyMgT3B0aW9uYWxseSBzcGVjaWZ5IGZpbGVuYW1lLCBkZWZhdWx0IGlzIG5ldHdvcmsgbmFtZQojIyBPcHRpb25hbGx5IHNwZWNpZnkgdHlwZTogUE5HIChkZWZhdWx0KSwgSlBFRywgUERGLCBQb3N0U2NyaXB0LCBTVkcgCgojIEV4cG9ydGluZyB0byBOREV4LCBhLmsuYS4g4oCcRHJvcGJveOKAnSBmb3IgbmV0d29ya3MKZXhwb3J0TmV0d29ya1RvTkRFeCh1c2VybmFtZSwgcGFzc3dvcmQsIFRSVUUpCiMjIEFjY291bnQgaW5mb3JtYXRpb24gKHVzZXJuYW1lIGFuZCBwYXNzd29yZCkgaXMgcmVxdWlyZWQgdG8gdXBsb2FkCiMjIFVzZSB1cGRhdGVOZXR3b3JrSW5OREV4IGlmIHRoZSBuZXR3b3JrIGhhcyBwcmV2aW91c2x5IGJlZW4gdXBsb2FkZWQKYGBgCgojIyBCdWlsZGluZyBNYXBzIG9mIEVucmljaG1lbnQgQW5hbHlzaXMgUmVzdWx0cwpUaGlzIHdvcmtmbG93IGlsbHVzdHJhdGVzIGhvdyB0byBwbG90IGFuIGFubm90YXRlZCBtYXAgb2YgZW5yaWNobWVudCByZXN1bHRzIHVzaW5nIHRoZSAgW0VucmljaG1lbnRNYXAgUGlwZWxpbmUgQ29sbGVjdGlvbiBvZiBhcHBzXShodHRwOi8vYXBwcy5jeXRvc2NhcGUub3JnL2FwcHMvZW5yaWNobWVudG1hcHBpcGVsaW5lY29sbGVjdGlvbikgaW4gQ3l0b3NjYXBlLiAgQW4gZW5yaWNobWVudCBtYXAgaXMgYSBuZXR3b3JrIHZpc3VhbGl6YXRpb24gb2YgcmVsYXRlZCBnZW5lc2V0cyBpbiB3aGljaCBub2RlcyBhcmUgZ2VuZSBzZXRzIChvciBwYXRod2F5cykgYW5kIGVkZ2Ugd2VpZ2h0IGluZGljYXRlcyB0aGUgb3ZlcmxhcCBpbiBtZW1iZXIgZ2VuZXMuIEZvbGxvd2luZyB0aGUgY29uc3RydWN0aW9uIG9mIHRoZSBlbnJpY2htZW50IG1hcCwgQXV0b0Fubm90YXRlIGNsdXN0ZXJzIHJlZHVuZGFudCBnZW5lIHNldHMgYW5kIHVzZXMgV29yZENsb3VkIHRvIGxhYmVsIHRoZSByZXN1bHRpbmcgY2x1c3Rlci4gVGhlIGNvZGUgdXNlcyB0aGUgQ29tbWFuZHMgaW50ZXJmYWNlIHRvIGludm9rZSBFbnJpY2htZW50TWFwIGFuZCBBdXRvQW5ub3RhdGUgYXBwcy4gQWZ0ZXIgaW5zdGFsbGluZyBhcHBzLCBydW4gY29tbWFuZHNBUEkoKSB0byBvcGVuIHRoZSBsaXZlIFN3YWdnZXIgZG9jdW1lbnRhdGlvbiB0byBicm93c2UgYW5kIGV4ZWN1dGUgY29tbWFuZC1saW5lIHN5bnRheC4KYGBge3J9Cmluc3RhbGxBcHAoIkVucmljaG1lbnRNYXAgUGlwZWxpbmUgQ29sbGVjdGlvbiIpICMgaW5zdGFsbHMgNCBhcHBzCiMgRG93bmxvYWQgc2FtcGxlIGdtdCBmaWxlIG9mIGh1bWFuIHBhdGh3YXlzCmdtdC5maWxlIDwtICJyY3kzX2VucmljaG1lbnRtYXAuZ210Igpkb3dubG9hZC5maWxlKGZpbGUucGF0aCgiaHR0cDovL2Rvd25sb2FkLmJhZGVybGFiLm9yZy9FTV9HZW5lc2V0cyIsCiAgICAgICAgICAgICAgICAgICAgICAgICJTZXB0ZW1iZXJfMDFfMjAxOS9IdW1hbi9zeW1ib2wvUGF0aHdheXMiLAogICAgICAgICAgICAgICAgICAgICAgICAiSHVtYW5fV2lraVBhdGh3YXlzX1NlcHRlbWJlcl8wMV8yMDE5X3N5bWJvbC5nbXQiKSwKICAgICAgICAgICAgICBnbXQuZmlsZSkKIyBSdW4gRW5yaWNobWVudE1hcCBidWlsZCBjb21tYW5kCmVtX2NvbW1hbmQgPC0gcGFzdGUoJ2VucmljaG1lbnRtYXAgYnVpbGQgYW5hbHlzaXNUeXBlPSJnZW5lcmljIicsCiAgICAgICAgICAgICAgICAgICAgImdtdEZpbGU9IiwgcGFzdGUoZ2V0d2QoKSwgZ210LmZpbGUsIHNlcD0iLyIpLAogICAgICAgICAgICAgICAgICAgICJwdmFsdWU9IiwgMSwKICAgICAgICAgICAgICAgICAgICAicXZhbHVlPSIsIDEsCiAgICAgICAgICAgICAgICAgICAgInNpbWlsYXJpdHljdXRvZmY9IiwwLjI1LAogICAgICAgICAgICAgICAgICAgICJjb2VmZmljaWVudHM9IiwiSkFDQ0FSRCIpCnByaW50KGVtX2NvbW1hbmQpCmNvbW1hbmRzR0VUKGVtX2NvbW1hbmQpCiMgUnVuIHRoZSBBdXRvQW5ub3RhdGUgY29tbWFuZAphYV9jb21tYW5kIDwtIHBhc3RlKCJhdXRvYW5ub3RhdGUgYW5ub3RhdGUtY2x1c3RlckJvb3N0ZWQiLAogICAgICAgICAgICAgICAgICAgICJjbHVzdGVyQWxnb3JpdGhtPU1DTCIsCiAgICAgICAgICAgICAgICAgICAgImxhYmVsQ29sdW1uPUVucmljaG1lbnRNYXA6OkdTX0RFU0NSIiwKICAgICAgICAgICAgICAgICAgICAibWF4V29yZHM9MyIpCnByaW50KGFhX2NvbW1hbmQpCmNvbW1hbmRzR0VUKGFhX2NvbW1hbmQpCiMgQW5ub3RhdGUgYSBzdWJuZXR3b3JrCmNyZWF0ZVN1Ym5ldHdvcmsoYygxOjQpLCJfX21jbENsdXN0ZXIiKQpjb21tYW5kc0dFVChhYV9jb21tYW5kKQpgYGAKCiMjIFZpc3VhbGl6aW5nIEludGVncmF0ZWQgTmV0d29yayBBbmFseXNpcyBVc2luZyBCaW9OZXQgClRoZSBbQmlvTmV0XShodHRwczovL2Jpb2NvbmR1Y3Rvci5vcmcvcGFja2FnZXMvcmVsZWFzZS9iaW9jL2h0bWwvQmlvTmV0Lmh0bWwpIHBhY2thZ2UgaW1wbGVtZW50cyBhbmFseXRpY2FsIG1ldGhvZHMgdG8gcGVyZm9ybSBpbnRlZ3JhdGVkIG5ldHdvcmsgYW5hbHlzaXMsIGUuZy4sIG9mIGdlbmUgZXhwcmVzc2lvbiBkYXRhIGFuZCBjbGluaWNhbCBzdXJ2aXZhbCBkYXRhIGluIHRoZSBjb250ZXh0IG9mIHByb3RlaW4tcHJvdGVpbiBpbnRlcmFjdGlvbiBuZXR3b3Jrcy4gUGFydG5lcmVkIHdpdGggUkN5MywgdGhlIGFuYWx5dGljYWwgcmVzdWx0cyBmcm9tIEJpb05ldCBjYW4gYmUgdmlzdWFsaXplZCBpbiBDeXRvc2NhcGUgd2l0aCB2YXN0bHkgbW9yZSBvcHRpb25zIGZvciBjdXN0b21pemF0aW9uLiBTdGFydGluZyB3aXRoIHRoZSBbIlF1aWNrIFN0YXJ0IiB0dXRvcmlhbF0oaHR0cHM6Ly9iaW9jb25kdWN0b3Iub3JnL3BhY2thZ2VzL3JlbGVhc2UvYmlvYy92aWduZXR0ZXMvQmlvTmV0L2luc3QvZG9jL1R1dG9yaWFsLnBkZikgZnJvbSBCaW9OZXQsIHdlIHBhc3MgdGhlIHJlc3VsdHMgZGlyZWN0bHkgdG8gQ3l0b3NjYXBlIGZvciB2aXN1YWxpemF0aW9uOgoKYGBge3J9CmxpYnJhcnkoQmlvTmV0KSAjIGluc3RhbGwgZnJvbSBCaW9jb25kdWN0b3IKbGlicmFyeShETEJDTCkgIyBpbnN0YWxsIGZyb20gQmlvY29uZHVjdG9yCmRhdGEoZGF0YUx5bSkKZGF0YShpbnRlcmFjdG9tZSkKIyMgVGhlIGZvbGxvd2luZyBzdGVwcyBhcmUgZnJvbSBCaW9OZXQncyBRdWljayBTdGFydCB0dXRvcmlhbDoKcHZhbHMgPC0gY2JpbmQodCA9IGRhdGFMeW0kdC5wdmFsLCBzID0gZGF0YUx5bSRzLnB2YWwpCnJvd25hbWVzKHB2YWxzKSA8LSBkYXRhTHltJGxhYmVsCnB2YWwgPC0gYWdnclB2YWxzKHB2YWxzLCBvcmRlciA9IDIsIHBsb3QgPSBGQUxTRSkKc3VibmV0IDwtIHN1Yk5ldHdvcmsoZGF0YUx5bSRsYWJlbCwgaW50ZXJhY3RvbWUpCnN1Ym5ldCA8LSBybVNlbGZMb29wcyhzdWJuZXQpCmZiIDwtIGZpdEJ1bU1vZGVsKHB2YWwsIHBsb3QgPSBGQUxTRSkKc2NvcmVzIDwtIHNjb3JlTm9kZXMoc3VibmV0LCBmYiwgZmRyID0gMC4wMDEpCm1vZHVsZSA8LSBydW5GYXN0SGVpbnooc3VibmV0LCBzY29yZXMpCmxvZ0ZDIDwtIGRhdGFMeW0kZGlmZgpuYW1lcyhsb2dGQykgPC0gZGF0YUx5bSRsYWJlbApwbG90TW9kdWxlKG1vZHVsZSwgc2NvcmVzID0gc2NvcmVzLCBkaWZmLmV4cHIgPSBsb2dGQykKCiMgVXNpbmcgUkN5MyB3ZSBjYW4gZ2VuZXJhdGUgYSBjdXN0b20gdmlzdWFsaXphdGlvbiBvZiB0aGUgc2FtZSBvdXRwdXQKIyMgQ3JlYXRlIG5ldHdvcmsgZnJvbSBncmFwaE5FTCBvYmplY3QgYW5kIGxvYWQgZGF0YSBjYWxjdWxhdGVkIGFib3ZlCmNyZWF0ZU5ldHdvcmtGcm9tR3JhcGgobW9kdWxlLCAibW9kdWxlIiwgIkJpb05ldCIpCmxvYWRUYWJsZURhdGEoYXMuZGF0YS5mcmFtZShzY29yZXMpKQpsb2FkVGFibGVEYXRhKGFzLmRhdGEuZnJhbWUobG9nRkMpKQojIyBTZXQgc3R5bGVzCnNldE5vZGVMYWJlbE1hcHBpbmcoImdlbmVTeW1ib2wiKQpzZXROb2RlRm9udFNpemVEZWZhdWx0KDE4KQpzZXROb2RlQm9yZGVyV2lkdGhEZWZhdWx0KDMuMCkKbG9nRkMubWF4LmFicyA8LSBtYXgoYWJzKG1pbihsb2dGQykpLCBhYnMobWF4KGxvZ0ZDKSkpIApzZXROb2RlQ29sb3JNYXBwaW5nKCdsb2dGQycsIGMoLWxvZ0ZDLm1heC5hYnMsIDAsIGxvZ0ZDLm1heC5hYnMpLCAKICAgICAgICAgICAgICAgICAgICBjKCcjNTU3N0ZGJywnI0ZGRkZGRicsJyNGRjc3NTUnKSwgZGVmYXVsdC5jb2xvciA9ICcjOTk5OTk5JykKY3JlYXRlQ29sdW1uRmlsdGVyKCJQb3NpdGl2ZSBzY29yZXMiLCAic2NvcmVzIixjKDAsbWF4KHNjb3JlcykpLCJCRVRXRUVOIikKc2V0Tm9kZVNoYXBlQnlwYXNzKGdldFNlbGVjdGVkTm9kZXMoKSwgIkVMTElQU0UiKQpjbGVhclNlbGVjdGlvbigpCmBgYAoKIyNQZXJmb3JtaW5nIEFkdmFuY2VkIEdyYXBoIEFuYWx5dGljcyBVc2luZyBSQkdMCkFzIGFuIGludGVyZmFjZSB0byB0aGUgQk9PU1QgbGlicmFyeSwgdGhlIFtSQkdMXShodHRwczovL2Jpb2NvbmR1Y3Rvci5vcmcvcGFja2FnZXMvcmVsZWFzZS9iaW9jL2h0bWwvUkJHTC5odG1sKSBCaW9jb25kdWN0b3IgcGFja2FnZSBvZmZlcnMgYW4gaW1wcmVzc2l2ZSBhcnJheSBvZiBhbmFseXRpY2FsIGZ1bmN0aW9ucyBmb3IgZ3JhcGhzLiBIZXJlIHdlIHdpbGwgc3RhcnQgd2l0aCBhIG5ldHdvcmsgaW4gQ3l0b3NjYXBlLCBsb2FkIGl0IGludG8gUiBhcyBhIGdyYXBoIG9iamVjdCwgcGVyZm9ybSBzaG9ydGVzdCBwYXRoIGNhbGN1bGF0aW9uIHVzaW5nIFJCR0wgYW5kIHRoZW4gdmlzdWFsaXplIHRoZSByZXN1bHRzIGJhY2sgaW4gQ3l0b3NjYXBlLgpgYGB7cn0KbGlicmFyeShSQkdMKSAjIGluc3RhbGwgZnJvbSBCaW9jb25kdWN0b3IKIyBDb252ZXJ0IGEgc2FtcGxlIEN5dG9zY2FwZSBuZXR3b3JrIHRvIGEgZ3JhcGggb2JqZWN0Cm9wZW5TZXNzaW9uKCkKZyA8LSBjcmVhdGVHcmFwaEZyb21OZXR3b3JrKCkKIyBJZGVudGlmeSBzdGFydCBhbmQgZmluaXNoIG5vZGVzIChzdHlsaW5nIGlzIG9wdGlvbmFsKQpzdGFydCA8LSAiWU5MMjE2VyIKZmluaXNoIDwtICJZRVIwNDBXIgpzZXROb2RlQm9yZGVyV2lkdGhCeXBhc3MoYyhzdGFydCwgZmluaXNoKSwgMjApCnNldE5vZGVCb3JkZXJDb2xvckJ5cGFzcyhzdGFydCwgIiMwMENDMzMiKQpzZXROb2RlQm9yZGVyQ29sb3JCeXBhc3MoZmluaXNoLCAiI0NDMDBDQyIpCiMgVXNlIFJCR0wgdG8gcGVyZm9ybSBzaG9ydGVzdCBwYXRoIGNhbGN1bGF0aW9uCnNob3J0ZXN0IDwtIHNwLmJldHdlZW4oZywgc3RhcnQsIGZpbmlzaCkKc2hvcnRlc3QkYFlOTDIxNlc6WUVSMDQwV2AkbGVuZ3RoCiNbMV0gNgpzaG9ydGVzdC5wYXRoIDwtIHNob3J0ZXN0JGBZTkwyMTZXOllFUjA0MFdgJHBhdGhfZGV0YWlsCiMgVmlzdWFsaXplIHJlc3VsdHMgaW4gQ3l0b3NjYXBlCnNlbGVjdE5vZGVzKHNob3J0ZXN0LnBhdGgsICJuYW1lIikKc2V0Tm9kZUJvcmRlcldpZHRoQnlwYXNzKHNob3J0ZXN0LnBhdGgsIDIwKQpjcmVhdGVTdWJuZXR3b3JrKCkKYGBgCgo=